#!/bin/bash

kernver=${KERNVER:-$(uname -r)}
arch=${ARCH:-$(uname -m)}
arch=${arch/i686/i386}
catver=whatever

LOG="/var/log/catalyst-install.log"

#patch_files(){
#    file_patch="${kernver:0:6}.patch"
#    if [[ -f "${file_patch}" ]]; then
#        patch -Np6 -i ${file_patch} || return 1
#    fi
#}


ati_make(){
###--- cut ---### ati's code from their make.sh file

# Copyright 1999-2005 ATI Technologies Inc., Markham, Ontario, CANADA.
# All Rights Reserved.    
# ==============================================================
# resolve if we are running a SMP enabled kernel

SMP=0

# 1
# grep in OsVersion string for SMP specific keywords
OsVersion=`uname -v`

if [ `echo $OsVersion | grep [sS][mM][pP] -c` -ne 0 ]; then
  SMP=1
  echo "OsVersion says: SMP=$SMP"
fi

# 2
# grep in /proc/ksyms for SMP specific kernel symbols
# use triggerlevel of 10 occurences
# (UP kernels might have 0-1, SMP kernels might have 32-45 or much more)

src_file=/proc/kallsyms

if [ -e $src_file ]; then
  if [ `fgrep smp $src_file -c` -gt 10 ]; then
    SMP=1
    echo "file $src_file says: SMP=$SMP"
  fi
fi

# 3
# linux/autoconf.h may contain this: #define CONFIG_SMP 1

# Before 2.6.33 autoconf.h is under linux/.
# For 2.6.33 and later autoconf.h is under generated/.
if [ -f /lib/modules/${kernver}/build/include/generated/autoconf.h ]; then
    autoconf_h=/lib/modules/${kernver}/build/include/generated/autoconf.h
else
    autoconf_h=/lib/modules/${kernver}/build/include/linux/autoconf.h
fi
src_file=$autoconf_h

if [ ! -e $src_file ]; then
  echo "Warning:"
  echo "kernel includes at /lib/modules/${kernver}/build/include not found or incomplete"
  echo "file: $src_file"
  echo ""
else
  if [ `cat $src_file | grep "#undef" | grep "CONFIG_SMP" -c` = 0 ]; then
    SMP=`cat $src_file | grep CONFIG_SMP | cut -d' ' -f3`
    echo "file $src_file says: SMP=$SMP"
  fi
fi

if [ "$SMP" = 0 ]; then
  echo "assuming default: SMP=$SMP"
fi

# act on final result
if [ ! "$SMP" = 0 ]; then
  smp="-SMP"
  def_smp=-D__SMP__
fi
# ==============================================================
# resolve whether we need to set PAGE_ATTR_FIX 
PAGE_ATTR_FIX=0

src_file=/proc/kallsyms

if [ -e $src_file ]; then
  if [ `fgrep " change_page_attr\$" $src_file -c` -gt 0 ]; then
    PAGE_ATTR_FIX=1
    echo "file $src_file says: PAGE_ATTR_FIX=$PAGE_ATTR_FIX"
  fi
fi
# ==============================================================
# resolve if we are running a MODVERSIONS enabled kernel

MODVERSIONS=0

# autoconf.h may contain this: #define CONFIG_MODVERSIONS 1
src_file=$autoconf_h
if [ ! -e $src_file ];
then
  echo "Warning:"
  echo "kernel includes at /lib/modules/${kernver}/build/include not found or incomplete"
  echo "file: $src_file"
  echo ""
else
  if [ `cat $src_file | grep "#undef" | grep "CONFIG_MODVERSIONS" -c` = 0 ]
  then
    MODVERSIONS=`cat $src_file | grep CONFIG_MODVERSIONS | cut -d' ' -f3`
    echo "file $src_file says: MODVERSIONS=$MODVERSIONS"
  fi
fi

if [ "$MODVERSIONS" = 0 ]
then
  echo "assuming default: MODVERSIONS=$MODVERSIONS"
fi

# act on final result
if [ ! "$MODVERSIONS" = 0 ]
then
  def_modversions="-DMODVERSIONS"
fi

# ==============================================================
# resolve if we are building for a kernel with a fix for CVE-2010-3081
# On kernels with the fix, use arch_compat_alloc_user_space instead
# of compat_alloc_user_space since the latter is GPL-only

COMPAT_ALLOC_USER_SPACE=compat_alloc_user_space

src_file=/lib/modules/${kernver}/build/arch/x86/include/asm/compat.h
if [ ! -e $src_file ];
then
  echo "Warning:"                                    
  echo "kernel includes at /lib/modules/${kernver}/build/include not found or incomplete"
  echo "file: $src_file"                              
  echo ""                                  
else
  if [ `cat $src_file | grep -c arch_compat_alloc_user_space` -gt 0 ]
  then
    COMPAT_ALLOC_USER_SPACE=arch_compat_alloc_user_space
  fi
  echo "file $src_file says: COMPAT_ALLOC_USER_SPACE=$COMPAT_ALLOC_USER_SPACE"
fi
# ==============================================================

###--- cut ---###
}

install_module-old(){
    echo ""
    echo "--------"
    date '+%Y-%m-%d %H:%M:%S'
    echo "Building fglrx module for ${kernver} kernel ..."
    echo "--------"
    if [ ! -d "/lib/modules/${kernver}/build" ]; then
      echo "Kernel header files are absent: directory /lib/modules/${kernver}/build doesn't exist! Game over"
      return 1
    fi
    workdir=$(mktemp -du /tmp/catalyst.XXXXXX)
    set -x
    cp "/usr/share/ati/build_mod" "${workdir}" -R
    cd "$workdir"
    patch -Np7 -i makefile_compat.patch || return 1
#    if [[ ${kernver:0:6} == "2.6.37" ]]  || [[ ${kernver:0:6} > "2.6.37" ]]; then
#        patch -Np6 -i sema_init.patch || return 1
#    fi
#    patch_files
    ati_make

    make -C /lib/modules/${kernver}/build SUBDIRS="`pwd`" ARCH=${arch} \
      MODFLAGS="-DMODULE -DATI -DFGL -DPAGE_ATTR_FIX=$PAGE_ATTR_FIX -DCOMPAT_ALLOC_USER_SPACE=$COMPAT_ALLOC_USER_SPACE $def_smp $def_modversions" \
      PAGE_ATTR_FIX=$PAGE_ATTR_FIX COMPAT_ALLOC_USER_SPACE=$COMPAT_ALLOC_USER_SPACE modules || return 1

    install -m755 -d "/lib/modules/${kernver}/video/"
    install -m644 fglrx.ko "/lib/modules/${kernver}/video/" || return 1

    depmod ${kernver}
    rm -rf "${workdir}"
    set +x
    echo "Ok."
}

install_module(){
    echo ""
    echo -e '\E[37;44m'"\033[1mBuilding catalyst ${catver} ${kernver} package for ${kernver} kernel ...\033[0m"
    echo "--------"
    if [ ! -d "/lib/modules/${kernver}/build" ]; then
      echo -e '\E[37;44m'"\033[1mKernel header files are absent: directory /lib/modules/${kernver}/build doesn't exist! Game over\033[0m"
      echo "--------"
      return 1
    fi
    workdir=$(mktemp -du /tmp/catalyst.XXXXXX)
#    set -x
    cp "/usr/share/ati/build_mod" "${workdir}" -R
    cd "$workdir"
    sed -i -e "s/_kernver=.*/_kernver=${kernver}/" PKGBUILD
    sed -i -e "s/pkgver=.*/pkgver=${catver}/" PKGBUILD
    sed -i -e "s/pkgrel=.*/pkgrel=${kernver/-/_}/" PKGBUILD
    if [ "${LOGNAME}" = "root" ]; then
      if [ "${user}" = "root" ]; then
       /usr/bin/makepkg -f -c --asroot || return 1
     	 else	
    	   chown ${user}:video ${workdir}
    	   chown ${user}:video ${workdir}/* >> /dev/null 2>&1
    	   su - ${user} -c "cd ${workdir} && /usr/bin/makepkg -f -c" || return 1
      fi
      else
	 /usr/bin/makepkg -f -c || return 1
    fi
    echo -e '\E[37;44m'"\033[1mOk. catalyst ${catver} ${kernver} package built succesfully. Installing ...\033[0m"
    if [ -e /usr/bin/sudo ]; then
        echo -e '\E[37;44m'"\033[1mIf it's asking for password - type YOUR password\033[0m"
        sudo /usr/bin/pacman -Ud ${workdir}/catalyst-${catver}-${kernver/-/_}-$(uname -m).pkg.* || return 1
    else
        echo -e '\E[37;44m'"\033[1mIf it's asking for password - type root password\033[0m"
        su - root -c "/usr/bin/pacman -Ud ${workdir}/catalyst-${catver}-${kernver/-/_}-$(uname -m).pkg.*" || return 1
    fi
    rm -rf "${workdir}"
#    set +x
    echo -e '\E[37;44m'"\033[1mDone.\033[0m"
}

build_all_modules-old(){
    for p in /lib/modules/*; do
     if [ -d $p/build ] && [ -d $p/kernel ]; then
      /usr/bin/catalyst_build_module ${p##*/lib/modules/}
     fi
    done
}
build_all_modules(){
    if [ "${LOGNAME}" = "root" ]; then
      echo "Please specify your (unprivileged) user name:"
      read user
    fi
    for p in /lib/modules/*; do
     if [ -d $p/build ] && [ -d $p/kernel ]; then
      /usr/bin/catalyst_build_module ${p##*/lib/modules/} ${user}
     fi
    done
}

remove_module-old(){
    for p in /lib/modules/*; do
	if [ ! -d $p/kernel ]; then  #check if /lib/modules/p/kernel directory does NOT exist
	  if [ -e $p/video/fglrx.ko ]; then
	    echo "+ removing fglrx module from $p"
	    rm "$p/video/fglrx.ko" &>/dev/null
	    rmdir -p "$p/video/" --ignore-fail-on-non-empty &>/dev/null
	  fi
	  if [ -d $p ]; then   #check if /lib/modules/p exist
	    if [ -z "$(ls $p)" ]; then   #check if /lib/modules/p is empty
	      echo "+ removing empty directory: $p"
	      rm -rf $p
		else echo "- $p looks like unused, maybe remove it manualy?"
	    fi
	  fi
	fi
    done
}
remove_module(){
    echo "Removing unused catalyst-{kernver} packages ..."
    for p in /lib/modules/*; do
	if [ ! -d $p/kernel ]; then
	    if [ -e $p/video/fglrx.ko ]; then
		  /usr/bin/pacman -Rd catalyst
	    fi
	fi
    done
}
remove_all_modules-old(){
    for p in /lib/modules/*; do
     if [ -e $p/video/fglrx.ko ]; then
      echo "+ removing fglrx module from $p"
      rm "$p/video/fglrx.ko" &>/dev/null
      rmdir -p "$p/video/" --ignore-fail-on-non-empty &>/dev/null
      depmod $(basename $p)
     fi
     if [ -d $p ]; then   #check if /lib/modules/p exist
      if [ -z "$(ls $p)" ]; then   #check if /lib/modules/p is empty
	echo "+ removing empty directory: $p"
	rm -rf $p
	elif [ ! -d $p/kernel ]; then
	  echo "- $p looks like unused, maybe remove it manualy?"
      fi
     fi
    done
}
remove_all_modules(){
    for p in /lib/modules/*; do
	if [ -e $p/video/fglrx.ko ]; then
	      /usr/bin/pacman -Rd --noconfirm catalyst
	fi
    done
}

auto_recompile(){
    # add hook fglrx to mkiniticpio
    hooks=$(grep ^HOOKS /etc/mkinitcpio.conf | grep fglrx)
    if [ "$hooks" = "" ]; then
        # add hook fglrx
        sed 's/^HOOKS="\([^"]*\)"/HOOKS="\1 fglrx"/' -i /etc/mkinitcpio.conf
    fi
    #add kernel26-headers to SyncFirst array of pacman.conf
    heads=$(grep ^SyncFirst /etc/pacman.conf | grep kernel26-headers)
    if [ "$heads" = "" ]; then
        # add heads
	sed '/^SyncFirst/s|$| kernel26-headers|' -i /etc/pacman.conf
    fi
    echo "----------------------------------------------------------------"
    echo "Answer 'Yes' whenever pacman ask you about updating"
    echo "'kernel26-headers' in first place"
    echo "----------------------------------------------------------------"
}

auto_recompile_off(){
    # remove hook fglrx
    sed '/^HOOKS/s/ *fglrx//' -i /etc/mkinitcpio.conf
    # remove heads
    sed '/^SyncFirst/s/ *kernel26-headers//' -i /etc/pacman.conf
    echo "Auto re-compilation is Disabled."
}

case "$1" in
    help|--help)
        echo "usage: $0 {version|all|remove|remove_all|auto|autooff}"
        echo "- with no specified kernel version it will use the current kernel version to build module"
	echo "- all will try to build fglrx modules for all working system's kernels"
        echo "- remove is removing unused catalyst {kernver} packages"
        echo "- remove_all is removing all catalyst {kernver} packages"
        echo "- auto will turn ON 'auto re-compilation of fglrx module with every kernel update'"
        echo "- autooff will turn off auto re-compilation of fglrx module"
        ;;
    remove)
        remove_module
        ;;
    remove_all)
        remove_all_modules
        ;;
    auto)
	auto_recompile
	;;
    autooff)
	auto_recompile_off
	;;
    all)
	build_all_modules
	;;
    *)
        test "$1" != "" && kernver="$1"
	if [ "$2" != "" ]; then user="$2"
          elif [ "${LOGNAME}" = "root" ]; then
	      echo "Please specify your (unprivileged) user name:"
	      read user
	fi
        install_module
        ;;
esac

